package com.cloud.dynamic.gateway.repository;

import cn.hutool.json.JSONUtil;
import com.cloud.dynamic.gateway.model.NacosConfigsQueryResult;
import com.sun.org.apache.xalan.internal.xsltc.dom.SortingIterator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class NacosRouteRepository implements RouteDefinitionRepository {

    @Autowired
    private RestTemplate restTemplate;

    private final String GROUP_NAME = "gateway-rules";

    @Override
    public Flux<RouteDefinition> getRouteDefinitions() {
        NacosConfigsQueryResult firstResult = getResult(1);

        if (firstResult == null || firstResult.getPageItems() == null) {
            return Flux.empty();
        }
        NacosConfigsQueryResult result = getResult(firstResult.getTotalCount());
        System.out.println("nacos 获取网关配置信息 " + result);
        List<RouteDefinition> routeDefinitions = result.getPageItems().stream()
                .map(nacosConfig -> JSONUtil.toBean(nacosConfig.getContent(), RouteDefinition.class))
                .collect(Collectors.toList());

        return Flux.fromIterable(routeDefinitions);
    }

    private NacosConfigsQueryResult getResult(int totalSize) {
        String url = "http://nacos.semfreud.com:81/nacos/v1/cs/configs?search=accurate&dataId=&group=gateway-rules&appName=&config_tags=&pageNo=1&pageSize=" + totalSize + "&tenant=&namespaceId=";
        String request = request(url, HttpMethod.GET, new LinkedMultiValueMap<>());
        return JSONUtil.toBean(request, NacosConfigsQueryResult.class);
    }

    private String request(String url, HttpMethod method, MultiValueMap<String, String> params) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(params, httpHeaders);
        ResponseEntity<String> exchange = restTemplate.exchange(url, method, entity, String.class, params);
        return exchange.getBody();
    }


    private void publishNacosConfig(String dataId, String content) {
        String format = "http://nacos.semfreud.com:81/nacos/v1/cs/configs";
        String url = String.format(format, dataId, GROUP_NAME, content);
        System.out.println(url);
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.put("dataId", Collections.singletonList(dataId));
        params.put("group", Collections.singletonList(GROUP_NAME));
        params.put("content", Collections.singletonList(content));
        System.out.println(params);
        String request = request(url, HttpMethod.POST, params);

        System.out.println("保存结果 : " + request);
    }

    private void deleteNacosConfig(String dataId){
        String format = "http://nacos.semfreud.com:81/nacos/v1/cs/configs?dataId=%s&group=%s";
        String url = String.format(format,dataId,GROUP_NAME);
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
//        params.put("dataId", Collections.singletonList(dataId));
        String request = request(url, HttpMethod.DELETE, params);
        System.out.println(request);
    }

    @Override
    public Mono<Void> save(Mono<RouteDefinition> route) {
        return route.flatMap(routeDefinition -> {
            String dataId = routeDefinition.getId() + ".json";
            String content = JSONUtil.toJsonStr(routeDefinition);
            System.out.println(content);
            publishNacosConfig(dataId, content);
            return Mono.empty();
        });
    }

    @Override
    public Mono<Void> delete(Mono<String> routeId) {
        return routeId.flatMap(id -> {
            System.out.println(id);
            deleteNacosConfig(id);
            System.out.println("========================delete hou");
            return Mono.defer(() -> Mono.error(
                    new NotFoundException("RouteDefinition not found: " + routeId)
            ));
        });
    }
}
